import { defineComponent, computed, inject, ref, reactive } from "vue";
import { Back, Right, Download, Upload, Top, Bottom, Delete, View, Edit, Close } from '@element-plus/icons-vue'
import './lowCodeEditor.scss'
import EdidtorBlock from "../components/EdidtorBlock";
import { useMenuDrop } from './useMenuDrag'
import { useElementFocus } from './useElementFocus'
import { useBlockdrag } from './useBlockDrag'
import { useCommonState } from './useCommon'
import { useWindowEvent } from './useWindowEvent'
import { cloneDeep } from 'loadsh'
import { $Dialog } from "../components/Dialog";
import { $DialogDropdown, DropdownItem } from "../components/DialogDropdown";
import EditorOperate from '../components/EditorOperate'


export default defineComponent({
    props: {
        modelValue: { type: Object }
    },
    emits: ['update:modelValue'],
    setup(props, ctx) {
        const data = computed({
            get() {
                return props.modelValue
            },
            set(newValue) {
                ctx.emit('update:modelValue', cloneDeep(newValue))
            }
        })

        const containerStyle = () => {
            return {
                width: data.value.container.width + 'px',
                height: data.value.container.height + 'px'
            }
        }

        const config = inject('config')

        const compenentList = config.componentList

        const containerLeftRef = ref(null)

        const containerRightRef = ref(null)

        // 目标ref
        const containerRef = ref(null)

        // 是否可编辑，默认编辑
        const isEdit = ref(false)

        // 预览页面
        const preview = ref(false)

        // 封装了拖拽事件：从左侧的组件中，拖拽到目标区域
        // 1、实现菜单拖拽功能
        const { dragstart, dragend } = useMenuDrop(containerRef, data)

        // 2、实现选中目标群区域的元素
        const { onBlockMousedown, onContainerMousedown, focusData, lastSelectBlock, clearBlockAllFocus } = useElementFocus(data, isEdit, (e) => containerMousemove(e))

        const { containerMousemove, markLine } = useBlockdrag(data, focusData, lastSelectBlock)

        const { stackCommands } = useCommonState(data, focusData)

        const { onDividerLeftDown, onDividerRightDown } = useWindowEvent(containerLeftRef, containerRightRef)

        // 更改数据源，让鼠标位于移动后的元素的中间位置
        const changeBlockItem = (item, index) => {
            const blockList = data.value.blocks
            blockList[index] = item
        }

        // 导出方法
        const exportData = () => {
            $Dialog({
                title: '导出json',
                content: JSON.stringify(data.value), // 把所有数据给content在弹框中显示
                footer: false
            })
        }

        // 导入方法
        const importData = () => {
            $Dialog({
                title: '导入json',
                content: '',
                footer: true,
                confirm(text) {
                    // data.value = JSON.parse(text)
                    // 为了可以记录状态，需要注册方法，在队列中
                    stackCommands.updateContainer(JSON.parse(text) || {})
                }
            })
        }

        const functionButtons = [
            { label: '撤销', icon: <el-icon size="14"> <Back /></el-icon>, handle: stackCommands.undo },
            { label: '还原', icon: <el-icon size="14"> <Right /></el-icon>, handle: stackCommands.redo },
            { label: '导出', icon: <el-icon size="14"><Download /></el-icon>, handle: exportData },
            { label: '导入', icon: <el-icon size="14"><Upload /></el-icon>, handle: importData },
            { label: '置顶', icon: <el-icon size="14"><Top /></el-icon>, handle: stackCommands.placeTop },
            { label: '置底', icon: <el-icon size="14"><Bottom /></el-icon>, handle: stackCommands.placeBottom },
            { label: '删除', icon: <el-icon size="14"><Delete /></el-icon>, handle: stackCommands.delete },
            {
                label: () => isEdit.value ? '编辑' : '关闭', icon: () => {
                    return isEdit.value ? <el-icon size="14"><Edit /></el-icon> : <el-icon size="14"><Close /></el-icon>
                }, handle: () => {
                    isEdit.value = !isEdit.value
                    clearBlockAllFocus()
                }
            },
            {
                label: '预览', icon: <el-icon size="14"><View /></el-icon>, handle: () => {
                    preview.value = true
                }
            },
        ]

        // 菜单列表
        const menuList = [
            {
                key: 'export', label: '查看', icon: <el-icon size="14"><Download /></el-icon>, handle: (block) => {
                    $Dialog({
                        title: '查看',
                        content: JSON.stringify(block)
                    })
                }
            },
            {
                key: 'import', label: '导入', icon: <el-icon size="14"><Upload /></el-icon>, handle: (block) => {
                    $Dialog({
                        title: '导入',
                        content: '',
                        footer: true,
                        confirm(text) {
                            text = JSON.parse(text)
                            console.log('block', block)
                            stackCommands.updateBlock(text, block)
                        }

                    })
                }
            },
            { key: 'placeTop', label: '置顶', icon: <el-icon size="14"><Top /></el-icon>, handle: stackCommands.placeTop },
            { key: 'placeBottom', label: '置底', icon: <el-icon size="14"><Bottom /></el-icon>, handle: stackCommands.placeBottom },
            { key: 'delete', label: '删除', icon: <el-icon size="14"><Delete /></el-icon>, handle: stackCommands.delete },
        ]

        // 点击区域中的元素右键点击弹出菜单
        const onBlockContextMenu = (event, block) => {
            event.preventDefault()
            const { clientX, clientY } = event
            $DialogDropdown({
                el: event.target,
                clickData: {
                    clientX,
                    clientY
                },
                content: () => <>
                    {
                        menuList.map((item) => {
                            return <DropdownItem icon={item.icon} key={item.key} label={item.label} onClick={() => item.handle(block)}></DropdownItem>
                        })
                    }
                </>
            })
        }

        return () => <>
            <div class="low-code-container">
                <div class="low-code-header">
                    <div class="low-code-menu">
                        {
                            functionButtons.map((item, index) => {
                                const label = typeof item.label === 'function' ? item.label() : item.label;
                                const icon = typeof item.icon === 'function' ? item.icon() : item.icon;
                                return <div key={index} onClick={item.handle} class="menu-item">
                                    <div>{icon}</div>
                                    <div>{label}</div>
                                </div>
                            })
                        }
                    </div >
                </div >
                <div class="low-code-main">
                    <div class='low-code-left' ref={containerLeftRef} >
                        {
                            compenentList.map((component, index) => {
                                return <div
                                    key={index}
                                    class="config-list-item"
                                    draggable="true"
                                    ondragstart={() => dragstart(component)}
                                    ondragend={() => dragend()}
                                >
                                    <span class="item-label">{component.label}</span>
                                    <span class="item-content">{component.preview()}</span>
                                </div>
                            })
                        }
                    </div>
                    <div class='divider' onmousedown={onDividerLeftDown}></div>
                    <div class="low-code-middle">
                        <div class="low-code-content-out">
                            <div class="inner-content" style={containerStyle()} ref={containerRef} onMousedown={onContainerMousedown}>
                                {
                                    data.value.blocks.map((block, index) => {
                                        return <EdidtorBlock
                                            class={{
                                                'no-edit-preview': isEdit.value,
                                                'editor-block-focus': block.focus
                                            }}
                                            key={block.key}
                                            itemIndex={index}
                                            block={block}
                                            changeBlockItem={changeBlockItem}
                                            onMousedown={(e) => onBlockMousedown(e, block, index)}
                                            onContextmenu={(e) => onBlockContextMenu(e, block)}
                                        ></EdidtorBlock>
                                    })
                                }
                                {markLine.x !== null && <div class="editor-x" style={{ left: markLine.x + 'px' }}></div>}
                                {markLine.y !== null && <div class="editor-y" style={{ top: markLine.y + 'px' }}></div>}
                            </div>
                        </div>
                    </div>
                    <div class='divider' onmousedown={onDividerRightDown}></div>
                    <div class='low-code-right' ref={containerRightRef}>
                        <EditorOperate
                            key={lastSelectBlock?.value?.key}
                            block={lastSelectBlock.value}
                            data={data.value}
                            updateContainer={stackCommands.updateContainer}
                            updateBlock={stackCommands.updateBlock}
                        ></EditorOperate>
                    </div>
                </div>
            </div >
            <div class="preview-container" v-show={preview.value}>
                <div class="preview-content">
                    <div class="preview-title-box">
                        <div class="preview-title">预览</div>
                        <div class="preview-close"><el-icon size="14" onClick={() => preview.value = false}><Close /></el-icon></div>
                    </div>
                    <div class="inner-content" style={containerStyle()} >
                        {
                            data.value.blocks.map((block, index) => {
                                return <EdidtorBlock
                                    class='no-edit-preview'
                                    key={block.key}
                                    itemIndex={index}
                                    block={block}
                                ></EdidtorBlock>
                            })
                        }
                    </div>
                </div>
            </div>
        </>
    }
})